package ${packageStr};
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.apache.commons.lang3.StringUtils;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@TableName("${tableName}")
public class ${entityName} {
    <#list filedList as filed>
        /***${filed.comment}*/
        <#if "${filed.idFiled}"=="1">
            @TableId(value = "${filed.column}", type = IdType.AUTO)
             <#elseif "${filed.idFiled}"=="2">
                @TableId(value = "${filed.column}")
            <#else>
                @TableField("${filed.column}")
        </#if>
        private ${filed.javaType} ${filed.name};
    </#list>

    <#if methodList?? && methodList?size>0>
        <#list methodList  as  method>
            /**${method.comment}*/
            public ${method.javaType} ${method.getName}(){
                return this.${method.filed};
            }

            /**${method.comment}*/
            public void ${method.setName}(${method.javaType} ${method.filed}){
                return this.${method.filed} = ${method.filed};
            }
        </#list>
    </#if>


    private final static java.util.Set<String> DATE_FILES = new java.util.HashSet<>();
    {
        <#if dateFileds?? && (dateFileds?size >0)>
         <#list dateFileds  as  dateFiled1>
            DATE_FILES.add("${dateFiled1}");
         </#list>
        </#if>
    }

     private final static java.util.Map<String,String> FILE_DESC_MAP = new java.util.HashMap(${filedSize});
     {

           <#list filedList  as  filed>
                FILE_DESC_MAP.put("${filed.name}","${filed.comment}");
            </#list>

     }

     private final static java.util.Map<String,String> FILE_COLUMNS_MAP = new java.util.HashMap(FILE_DESC_MAP.size());
     {
         <#list filedList  as  filed>
             FILE_COLUMNS_MAP.put("${filed.name}","${filed.column}");
         </#list>
     }

     <#if "${localDateTime}"=="1">
        <#if ""== "${localDateTimeUtils}">
         private static final java.time.format.DateTimeFormatter DATE_TIME_FORMATTER = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        </#if>
        private void jsonArrayAddStrOfLocalDateTime(String commend, com.google.gson.JsonArray jsonArray, java.time.LocalDateTime value){
            if(java.util.Objects.isNull(value)){
                return;
            }
            <#if ""== "${localDateTimeUtils}">
                jsonArrayAddStr(commend,DATE_TIME_FORMATTER.format(value),jsonArray);
            <#else>
                jsonArrayAddStr(commend,${localDateTimeUtils}.format(value),jsonArray);
            </#if>
        }

        private void jsonArrayUpdateOfLocalDateTime(String commend, java.time.LocalDateTime newValue, java.time.LocalDateTime oldValue, com.google.gson.JsonArray jsonArray){
            <#if ""== "${localDateTimeUtils}">
                  String newDateStr = java.util.Objects.isNull(newValue)?null:DATE_TIME_FORMATTER.format(newValue);
                  String oldDateStr = java.util.Objects.isNull(oldValue)?null:DATE_TIME_FORMATTER.format(oldValue);
            <#else>
                 String newDateStr = java.util.Objects.isNull(newValue)?null:${localDateTimeUtils}.format(newValue);
                 String oldDateStr = java.util.Objects.isNull(oldValue)?null:${localDateTimeUtils}.format(oldValue);
            </#if>
            jsonArrayUpdate(commend, newDateStr, oldDateStr, jsonArray);
        }
     <#else>
        private void jsonArrayAddStrOfDate(String commend, java.util.Date value, com.google.gson.JsonArray jsonArray){
            if(java.util.Objects.isNull(value)){
                return;
            }
            jsonArrayAddStr(commend,${dateUtils}.format(value),jsonArray);
        }

        private void jsonArrayUpdateOfDate(String commend, java.util.Date newValue, java.util.Date oldValue, com.google.gson.JsonArray jsonArray){
            String newDateStr = java.util.Objects.isNull(newValue)?null: ${dateUtils}.format(newValue);
            String oldDateStr = java.util.Objects.isNull(oldValue)?null: ${dateUtils}.format(oldValue);
            jsonArrayUpdate(commend, newDateStr, oldDateStr, jsonArray);
        }
     </#if>

     private <T>void jsonArrayAddStr(String commend,T value,com.google.gson.JsonArray jsonArray){
        boolean flag = java.util.Optional.ofNullable(value).map(val -> {
            return org.apache.commons.lang3.StringUtils.isNotEmpty(val.toString());
        }).orElse(Boolean.FALSE);
        if (flag && org.apache.commons.lang3.StringUtils.isNotEmpty(commend)) {
            jsonArray.add(commend + ":『"+value+"』");
        }
     }

     private <T> void jsonArrayUpdate(String commend, T newValue, T oldValue, com.google.gson.JsonArray jsonArray){
        boolean flag = java.util.Optional.ofNullable(newValue).map(value -> {
            return org.apache.commons.lang3.StringUtils.isNotEmpty(value.toString()) && !java.util.Objects.equals(value, oldValue);
        }).orElse(Boolean.FALSE);
        if (flag && org.apache.commons.lang3.StringUtils.isNotEmpty(commend)) {
            Object value = java.util.Objects.isNull(oldValue)?"":oldValue;
            StringBuilder builder = new StringBuilder();
            builder.append(commend+":从 『").append(value).append("』修改为『").append(newValue).append("』");
            jsonArray.add(builder.toString());
        }

     }

     /***通过反射获取实体的指定属性的值*/
      private <T> T getResult(String fieldName, ${entityName} entity) {
         try{
            Class<?> aClass = entity.getClass();
            java.beans.BeanInfo beanInfo = java.beans.Introspector.getBeanInfo(aClass);
            java.util.Optional<java.beans.PropertyDescriptor> optional = java.util.Arrays.stream(beanInfo.getPropertyDescriptors()).filter(p -> {
                return java.util.Objects.equals(p.getName(), fieldName);
            }).findFirst();
            return optional.isPresent() ? (T) optional.get().getReadMethod().invoke(entity) : null;
         } catch (java.beans.IntrospectionException e) {
            log.error("读属性取值异常:[{}][{}]", fieldName, e.getMessage(), e);
         } catch (java.lang.IllegalAccessException e) {
            log.error("读属性取值异常:[{}][{}]", fieldName, e.getMessage(), e);
         } catch (java.lang.reflect.InvocationTargetException e) {
            log.error("读属性取值异常:[{}][{}]", fieldName, e.getMessage(), e);
         }
         return null;
      }

      /**数据描述(字段对应的值描述)*/
      public  String toFiledAndDataDesc(){
        com.google.gson.JsonArray jsonArray = new com.google.gson.JsonArray(FILE_DESC_MAP.size());
        FILE_DESC_MAP.forEach((key, val) -> {
            if (DATE_FILES.contains(key)) {
                 <#if "${localDateTime}"=="1">
                    jsonArrayAddStrOfLocalDateTime(val,jsonArray, getResult(key, this));
                 <#else>
                    jsonArrayAddStrOfDate(val, getResult(key, this), jsonArray);
                 </#if>
            } else {
                jsonArrayAddStr(val, getResult(key, this), jsonArray);
            }
        });
        return jsonArray.size()== 0?"":jsonArray.toString();
      }
        /**数据描述(列名对应的值描述)*/
      public String toColumnsDataDesc(){
         com.google.gson.JsonArray jsonArray = new com.google.gson.JsonArray(FILE_DESC_MAP.size());
         FILE_DESC_MAP.forEach((key, val) -> {
            if (DATE_FILES.contains(key)) {
                 <#if "${localDateTime}"=="1">
                    jsonArrayAddStrOfLocalDateTime(FILE_COLUMNS_MAP.get(key),jsonArray, getResult(key, this));
                 <#else>
                    jsonArrayAddStrOfDate(FILE_COLUMNS_MAP.get(key), getResult(key, this), jsonArray);
                 </#if>
            } else {
                jsonArrayAddStr(FILE_COLUMNS_MAP.get(key), getResult(key, this), jsonArray);
            }
         });
         return jsonArray.size()== 0?"":jsonArray.toString();
      }


      /**数据修改值描述（字段说明）*/
      public String toUpdateParameter(${entityName} oldEntity){
        com.google.gson.JsonArray jsonArray = new com.google.gson.JsonArray(FILE_DESC_MAP.size());
        if (java.util.Objects.isNull(oldEntity)) { return "";}
        FILE_DESC_MAP.forEach((key, val) -> {
            if (DATE_FILES.contains(key)) {
                  <#if "${localDateTime}"=="1">
                    jsonArrayUpdateOfLocalDateTime(val, getResult(key, this), getResult(key, oldEntity), jsonArray);
                 <#else>
                    jsonArrayUpdateOfDate(val, getResult(key, this), getResult(key, oldEntity), jsonArray);
                 </#if>
            }else {
                jsonArrayUpdate(val, getResult(key, this), getResult(key, oldEntity), jsonArray);
            }
        });
        return jsonArray.size()== 0?"":jsonArray.toString();
      }

      public String toColumnsUpdateDataDesc(${entityName} oldEntity){
        if (java.util.Objects.isNull(oldEntity)) { return "";}
        com.google.gson.JsonArray jsonArray = new com.google.gson.JsonArray(FILE_DESC_MAP.size());
        FILE_DESC_MAP.forEach((key, val) -> {
            if (DATE_FILES.contains(key)) {
                 <#if "${localDateTime}"=="1">
                    jsonArrayUpdateOfLocalDateTime(FILE_COLUMNS_MAP.get(key), getResult(key, this), getResult(key, oldEntity), jsonArray);
                 <#else>
                   jsonArrayUpdateOfDate(FILE_COLUMNS_MAP.get(key), getResult(key, this), getResult(key, oldEntity), jsonArray);
                 </#if>
            } else {
                jsonArrayUpdate(FILE_COLUMNS_MAP.get(key), getResult(key, this), getResult(key, oldEntity), jsonArray);
            }
        });
        return jsonArray.size()== 0?"":jsonArray.toString();
      }

       @Override
       public String toString() { return ${jsonUtilMethod}(this);}
}